package com.chentf.spring.annotation.config;

import com.chentf.spring.annotation.bean.Color;
import com.chentf.spring.annotation.bean.ColorFactoryBean;
import com.chentf.spring.annotation.bean.Person;
import com.chentf.spring.annotation.bean.Red;
import com.chentf.spring.annotation.condition.LinuxCondition;
import com.chentf.spring.annotation.condition.MyImportBeanDefinitionRegistrar;
import com.chentf.spring.annotation.condition.MyImportSelector;
import com.chentf.spring.annotation.condition.WindowsCondition;
import org.springframework.context.annotation.*;

// 对配置类中的组件进行统一设置
//@Conditional({WindowsCondition.class}) // 满足当前条件，这个类中配置的所有bean注册才能生效
@Configuration
// @Import快速地导入组件，id默认是组件的全类名,支持导入多个类
@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class PersonConfig2 {

    /**
     * 单实例bean注意的事项
     * 单实例bean是整个应用所共享的，所以需要考虑到线程安全问题，
     * 之前在玩SpringMVC的时候，SpringMVC中的Controller默认是单例的，有些开发者在Controller中创建了一些变量，
     * 那么这些变量实际上就变成共享的了，Controller又可能会被很多线程同时访问，这些线程并发去修改Controller中的共享变量，
     * 此时很有可能会出现数据错乱的问题，所以使用的时候需要特别注意。
     *
     * 多实例bean注意的事项
     * 多实例bean每次获取的时候都会重新创建，如果这个bean比较复杂，创建时间比较长，那么就会影响系统的性能，因此这个地方需要注意点。
     */
    @Bean
//    @Scope("prototype") // 通过@Scope注解来指定该bean的作用范围，也可以说成是调整作用域
    @Lazy
    public Person person() {
        System.out.println("给容器中添加咱们这个Person对象...");
        return new Person("chentf",35,"chentf");
    }

    @Conditional(LinuxCondition.class)
    @Bean("bill")
    public Person person01() {
        return new Person("唐长老", 62, "bill");
    }

    @Conditional(WindowsCondition.class)
    @Bean("linus")
    public Person person02() {
        return new Person("熏悟空", 48, "linus");
    }

    /**
     * 当配置文件中标签的class属性配置的实现类是FactoryBean时，
     * 通过 getBean()方法返回的不是FactoryBean本身，而是FactoryBean#getObject()方法所返回的对象，
     * 相当于FactoryBean#getObject()代理了getBean()方法。
     * @return
     */
    @Bean
    public ColorFactoryBean colorFactoryBean() {
        return new ColorFactoryBean();
    }

}
